import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:args/command_runner.dart';
import 'package:gate_cli/models/json_clz.dart';
import 'package:gate_cli/models/res_config.dart';
import 'package:gate_cli/utils/command_util.dart';
import 'package:gate_cli/utils/json_command_util.dart';
import 'package:gate_cli/utils/list_extension.dart';
import 'package:dart_style/dart_style.dart';

class JsonCommand extends Command<String> {
  ResConfig _resConfig = ResConfig(dark: ResDark(), json: ResJson());

  @override
  String get description => "Json 转Dart类";

  @override
  String get name => "json";

  @override
  List<String> get aliases => ['j'];

  JsonCommand() {
    argParser.addOption('config', abbr: 'c', help: '配置文件');
  }

  @override
  FutureOr<String>? run() {
    final config = CommandUtil.loadConfig(argResults?['config'] ?? "");
    _resConfig = ResConfig.fromYaml(config);
    CommandUtil.addKeywords(_resConfig.json.keys);
    writeCode();
    return "";
  }

  void writeCode() {
    // 1. 获取Json文件
    List<String> json = _loadJson();
    // 2. 解析Json文件
    List<JsonClz> jsonClz = _parseJson(json);
    // 3. 转dart文件
    _codeBuild(jsonClz);
    // 4. 自动构建Json解析
    _buildRunner();
  }

  void _buildRunner() async {
    await Process.start('flutter', ['pub', 'run', 'build_runner', 'build', '--delete-conflicting-outputs']);
  }

  List<String> _loadJson() {
    final res = _resConfig.json.resource;
    final resPath = res.startsWith('/') ? res.substring(1) : res;
    final directory = Directory('${Directory.current.path}/$resPath');
    if (!directory.existsSync()) {
      print('JSON目录 $res 未找到');
      return [];
    }
    return directory.listSync().map((e) => e.path).toList();
  }

  List<JsonClz> _parseJson(List<String> json) {
    return json.map((e) => _buildJsonClz(e)).whereType<JsonClz>().toList();
  }

  JsonClz? _buildJsonClz(String file) {
    final fileType = file.split('.').lastOrNull ?? "";
    if (fileType.toLowerCase() != 'json') return null;
    final jsonFile = File(file);
    if (!jsonFile.existsSync()) {
      return null;
    }
    final clzName = file.split('/').lastOrNull?.split('.').first ?? "";
    if (clzName.isEmpty) return null;
    final jsonContent = jsonFile.readAsStringSync();
    Map<String, dynamic> jsonMap = json.decode(jsonContent);
    final jsonClz = JsonClz.fromMap(clzName, jsonMap, _resConfig.json);
    return jsonClz;
  }

  void _codeBuild(List<JsonClz> jsonClz) {
    final pkg = _resConfig.json.package;
    final pkgDir = Directory(pkg);
    if (!pkgDir.existsSync()) {
      pkgDir.createSync(recursive: true);
    }
    final formatter = DartFormatter(fixes: StyleFix.all);
    for (var clz in jsonClz) {
      final header = JsonCommandUtil.buildHeader(clz, _resConfig.json);
      final content = JsonCommandUtil.buildClz(clz, _resConfig.json);
      if (content == null || content.isEmpty) continue;
      _writeContent(File('$pkg/${clz.fileName}.dart'), formatter.format(header + content));
    }
  }

  void _writeContent(File file, String content) {
    if (content.isEmpty) return;
    final exits = file.existsSync();
    if (exits && _resConfig.json.skipIfExit) return;
    file.writeAsStringSync(content, mode: FileMode.write, flush: true);
  }
}
